pub mod technical_indicators;

use serde::{Deserialize, Serialize};

/// 高级技术指标结果
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AdvancedIndicatorResult {
    /// 趋势强度指数
    pub tsi: Vec<f64>,
    /// 钱德动量摆动指标
    pub cmo: Vec<f64>,
    /// 终极波动指标
    pub uo: Vec<f64>,
    /// 威廉姆斯分形
    pub williams_fractals: Vec<bool>,
    /// 阿隆指标
    pub aroon: Vec<(f64, f64)>,
    /// 克罗符趋向指标
    pub kst: Vec<f64>,
    /// 相对强弱指数修正指标
    pub rsi_modified: Vec<f64>,
    /// 动态动量指数
    pub dmi: Vec<f64>,
    /// 量价趋势指标
    pub pvt: Vec<f64>,
    /// 资金流量指标
    pub mfi_modified: Vec<f64>,
}

/// 高级技术指标计算器
pub struct AdvancedIndicatorCalculator {
    /// 计算窗口大小
    window_size: usize,
    /// 是否使用修正方法
    use_modified: bool,
}

impl AdvancedIndicatorCalculator {
    /// 计算所有高级指标
    pub fn calculate_indicators(
        &self,
        close_prices: &[f64],
        high_prices: &[f64],
        low_prices: &[f64],
        volumes: &[f64],
    ) -> AdvancedIndicatorResult {
        AdvancedIndicatorResult {
            tsi: self.calculate_tsi(close_prices, 13, 25),
            cmo: self.calculate_cmo(close_prices, 14),
            uo: self.calculate_uo(high_prices, low_prices, close_prices),
            williams_fractals: self.calculate_williams_fractals(high_prices, low_prices),
            aroon: self.calculate_aroon(high_prices, low_prices, 14),
            kst: self.calculate_kst(close_prices),
            rsi_modified: self.calculate_modified_rsi(close_prices, 14),
            dmi: self.calculate_dmi(high_prices, low_prices, close_prices, 14),
            pvt: self.calculate_pvt(close_prices, volumes),
            mfi_modified: self.calculate_modified_mfi(high_prices, low_prices, close_prices, volumes, 14),
        }
    }

    /// 创建新的高级指标计算器
    pub fn new(window_size: usize) -> Self {
        Self {
            window_size,
            use_modified: true,
        }
    }

    /// 计算趋势强度指数 (TSI)
    pub fn calculate_tsi(&self, prices: &[f64], short_period: usize, long_period: usize) -> Vec<f64> {
        let mut tsi = Vec::with_capacity(prices.len());
        if prices.len() < long_period {
            return tsi;
        }

        // 计算价格动量
        let momentum: Vec<f64> = prices.windows(2)
            .map(|w| w[1] - w[0])
            .collect();

        // 计算双重指数平滑
        let mut first_ema = self.exponential_moving_average(&momentum, long_period);
        first_ema = self.exponential_moving_average(&first_ema, short_period);

        let mut abs_momentum: Vec<f64> = momentum.iter().map(|&x| x.abs()).collect();
        let mut second_ema = self.exponential_moving_average(&abs_momentum, long_period);
        second_ema = self.exponential_moving_average(&second_ema, short_period);

        // 计算TSI
        for i in 0..first_ema.len() {
            if second_ema[i] != 0.0 {
                tsi.push(100.0 * first_ema[i] / second_ema[i]);
            } else {
                tsi.push(0.0);
            }
        }

        tsi
    }

    /// 计算钱德动量摆动指标 (CMO)
    pub fn calculate_cmo(&self, prices: &[f64], period: usize) -> Vec<f64> {
        let mut cmo = Vec::with_capacity(prices.len());
        if prices.len() < period {
            return cmo;
        }

        for i in period..prices.len() {
            let mut up_sum = 0.0;
            let mut down_sum = 0.0;

            for j in (i - period + 1)..=i {
                let diff = prices[j] - prices[j - 1];
                if diff > 0.0 {
                    up_sum += diff;
                } else {
                    down_sum -= diff;
                }
            }

            if up_sum + down_sum != 0.0 {
                cmo.push(100.0 * (up_sum - down_sum) / (up_sum + down_sum));
            } else {
                cmo.push(0.0);
            }
        }

        cmo
    }

    /// 计算终极波动指标 (UO)
    pub fn calculate_uo(&self, high: &[f64], low: &[f64], close: &[f64]) -> Vec<f64> {
        let mut uo = Vec::with_capacity(close.len());
        if close.len() < 28 {
            return uo;
        }

        for i in 27..close.len() {
            let bp = close[i] - low[i].min(close[i - 1]);
            let tr = high[i].max(close[i - 1]) - low[i].min(close[i - 1]);

            // 计算不同周期的买压平均值
            let avg7 = self.calculate_buying_pressure(&close[i-6..=i], &high[i-6..=i], &low[i-6..=i]);
            let avg14 = self.calculate_buying_pressure(&close[i-13..=i], &high[i-13..=i], &low[i-13..=i]);
            let avg28 = self.calculate_buying_pressure(&close[i-27..=i], &high[i-27..=i], &low[i-27..=i]);

            // 计算UO
            let uo_value = 100.0 * (4.0 * avg7 + 2.0 * avg14 + avg28) / 7.0;
            uo.push(uo_value);
        }

        uo
    }

    /// 计算威廉姆斯分形
    pub fn calculate_williams_fractals(&self, high: &[f64], low: &[f64]) -> Vec<bool> {
        let mut fractals = vec![false; high.len()];
        if high.len() < 5 {
            return fractals;
        }

        for i in 2..high.len()-2 {
            // 上分形
            if high[i] > high[i-2] && high[i] > high[i-1] &&
               high[i] > high[i+1] && high[i] > high[i+2] {
                fractals[i] = true;
            }
            // 下分形
            if low[i] < low[i-2] && low[i] < low[i-1] &&
               low[i] < low[i+1] && low[i] < low[i+2] {
                fractals[i] = true;
            }
        }

        fractals
    }

    /// 计算阿隆指标
    pub fn calculate_aroon(&self, high: &[f64], low: &[f64], period: usize) -> Vec<(f64, f64)> {
        let mut aroon = Vec::with_capacity(high.len());
        if high.len() < period {
            return aroon;
        }

        for i in period..high.len() {
            let mut highest_idx = i - period;
            let mut lowest_idx = i - period;

            // 找到周期内最高点和最低点的位置
            for j in (i - period + 1)..=i {
                if high[j] > high[highest_idx] {
                    highest_idx = j;
                }
                if low[j] < low[lowest_idx] {
                    lowest_idx = j;
                }
            }

            // 计算Aroon指标
            let aroon_up = 100.0 * (period - (i - highest_idx)) as f64 / period as f64;
            let aroon_down = 100.0 * (period - (i - lowest_idx)) as f64 / period as f64;

            aroon.push((aroon_up, aroon_down));
        }

        aroon
    }

    /// 计算克罗符趋向指标 (KST)
    pub fn calculate_kst(&self, prices: &[f64]) -> Vec<f64> {
        let mut kst = Vec::with_capacity(prices.len());
        if prices.len() < 63 {
            return kst;
        }

        // 计算不同周期的ROC
        let roc10 = self.calculate_roc(prices, 10);
        let roc15 = self.calculate_roc(prices, 15);
        let roc20 = self.calculate_roc(prices, 20);
        let roc30 = self.calculate_roc(prices, 30);

        // 计算移动平均
        let ma10 = self.simple_moving_average(&roc10, 10);
        let ma10_15 = self.simple_moving_average(&roc15, 10);
        let ma10_20 = self.simple_moving_average(&roc20, 10);
        let ma15_30 = self.simple_moving_average(&roc30, 15);

        // 合并结果
        let start = 62; // 考虑所有周期后的起始位置
        for i in start..prices.len() {
            let idx = i - start;
            let kst_value = ma10[idx] + 2.0 * ma10_15[idx] + 3.0 * ma10_20[idx] + 4.0 * ma15_30[idx];
            kst.push(kst_value);
        }

        kst
    }

    /// 计算修正的RSI指标
    pub fn calculate_modified_rsi(&self, prices: &[f64], period: usize) -> Vec<f64> {
        let mut rsi_mod = Vec::with_capacity(prices.len());
        if prices.len() < period {
            return rsi_mod;
        }

        // 计算标准RSI
        let mut gains = Vec::new();
        let mut losses = Vec::new();

        for i in 1..prices.len() {
            let change = prices[i] - prices[i - 1];
            gains.push(change.max(0.0));
            losses.push((-change).max(0.0));
        }

        let mut avg_gain = gains[0..period].iter().sum::<f64>() / period as f64;
        let mut avg_loss = losses[0..period].iter().sum::<f64>() / period as f64;

        // 添加波动率调整
        for i in period..prices.len() {
            if avg_loss != 0.0 {
                let rsi = 100.0 - (100.0 / (1.0 + avg_gain / avg_loss));
                
                // 计算当前波动率
                let volatility = self.calculate_volatility(&prices[i.saturating_sub(20)..=i]);
                
                // 调整RSI值
                let adjusted_rsi = rsi * (1.0 + volatility);
                rsi_mod.push(adjusted_rsi.min(100.0));
            } else {
                rsi_mod.push(100.0);
            }

            // 更新平均值
            avg_gain = (avg_gain * (period - 1) as f64 + gains[i - 1]) / period as f64;
            avg_loss = (avg_loss * (period - 1) as f64 + losses[i - 1]) / period as f64;
        }

        rsi_mod
    }

    /// 计算动态动量指数 (DMI)
    pub fn calculate_dmi(&self, high: &[f64], low: &[f64], close: &[f64], period: usize) -> Vec<f64> {
        let mut dmi = Vec::with_capacity(close.len());
        if close.len() < period {
            return dmi;
        }

        let mut tr = Vec::new();
        let mut plus_dm = Vec::new();
        let mut minus_dm = Vec::new();

        // 计算TR和DM
        for i in 1..close.len() {
            let tr_value = (high[i] - low[i])
                .max((high[i] - close[i - 1]).abs())
                .max((low[i] - close[i - 1]).abs());
            tr.push(tr_value);

            let plus_dm_value = if high[i] - high[i - 1] > low[i - 1] - low[i] {
                (high[i] - high[i - 1]).max(0.0)
            } else {
                0.0
            };
            plus_dm.push(plus_dm_value);

            let minus_dm_value = if low[i - 1] - low[i] > high[i] - high[i - 1] {
                (low[i - 1] - low[i]).max(0.0)
            } else {
                0.0
            };
            minus_dm.push(minus_dm_value);
        }

        // 计算平滑值
        let smooth_tr = self.exponential_moving_average(&tr, period);
        let smooth_plus_dm = self.exponential_moving_average(&plus_dm, period);
        let smooth_minus_dm = self.exponential_moving_average(&minus_dm, period);

        // 计算DI和DMI
        for i in 0..smooth_tr.len() {
            if smooth_tr[i] != 0.0 {
                let plus_di = 100.0 * smooth_plus_dm[i] / smooth_tr[i];
                let minus_di = 100.0 * smooth_minus_dm[i] / smooth_tr[i];
                let dmi_value = if plus_di + minus_di != 0.0 {
                    100.0 * (plus_di - minus_di).abs() / (plus_di + minus_di)
                } else {
                    0.0
                };
                dmi.push(dmi_value);
            } else {
                dmi.push(0.0);
            }
        }

        dmi
    }

    /// 计算量价趋势指标 (PVT)
    pub fn calculate_pvt(&self, prices: &[f64], volumes: &[f64]) -> Vec<f64> {
        let mut pvt = Vec::with_capacity(prices.len());
        if prices.len() != volumes.len() || prices.len() < 2 {
            return pvt;
        }

        pvt.push(0.0); // 初始值

        for i in 1..prices.len() {
            let price_change = (prices[i] - prices[i - 1]) / prices[i - 1];
            let pvt_value = pvt[i - 1] + volumes[i] * price_change;
            pvt.push(pvt_value);
        }

        pvt
    }

    /// 计算修正的资金流量指标 (Modified MFI)
    pub fn calculate_modified_mfi(&self, high: &[f64], low: &[f64], close: &[f64], volumes: &[f64], period: usize) -> Vec<f64> {
        let mut mfi_mod = Vec::with_capacity(close.len());
        if close.len() < period || close.len() != volumes.len() {
            return mfi_mod;
        }

        let mut money_flow = Vec::new();
        let mut typical_prices = Vec::new();

        // 计算典型价格和资金流量
        for i in 0..close.len() {
            let tp = (high[i] + low[i] + close[i]) / 3.0;
            typical_prices.push(tp);
            money_flow.push(tp * volumes[i]);
        }

        // 添加波动率权重
        for i in period..close.len() {
            let mut pos_flow = 0.0;
            let mut neg_flow = 0.0;

            for j in (i - period + 1)..=i {
                if typical_prices[j] > typical_prices[j - 1] {
                    pos_flow += money_flow[j];
                } else {
                    neg_flow += money_flow[j];
                }
            }

            // 计算波动率调整因子
            let volatility = self.calculate_volatility(&close[i.saturating_sub(20)..=i]);
            let volume_trend = self.calculate_volume_trend(&volumes[i.saturating_sub(20)..=i]);

            if neg_flow != 0.0 {
                let raw_mfi = 100.0 - (100.0 / (1.0 + pos_flow / neg_flow));
                // 应用波动率和成交量趋势调整
                let adjusted_mfi = raw_mfi * (1.0 + volatility) * (1.0 + volume_trend);
                mfi_mod.push(adjusted_mfi.min(100.0));
            } else {
                mfi_mod.push(100.0);
            }
        }

        mfi_mod
    }

    // 辅助方法

    /// 计算简单移动平均
    fn simple_moving_average(&self, data: &[f64], period: usize) -> Vec<f64> {
        let mut sma = Vec::with_capacity(data.len());
        if data.len() < period {
            return sma;
        }

        let mut sum = data[0..period].iter().sum::<f64>();
        sma.push(sum / period as f64);

        for i in period..data.len() {
            sum = sum - data[i - period] + data[i];
            sma.push(sum / period as f64);
        }

        sma
    }

    /// 计算指数移动平均
    fn exponential_moving_average(&self, data: &[f64], period: usize) -> Vec<f64> {
        let mut ema = Vec::with_capacity(data.len());
        if data.is_empty() {
            return ema;
        }

        let multiplier = 2.0 / (period + 1) as f64;
        ema.push(data[0]);

        for i in 1..data.len() {
            let value = (data[i] - ema[i - 1]) * multiplier + ema[i - 1];
            ema.push(value);
        }

        ema
    }

    /// 计算变化率
    fn calculate_roc(&self, data: &[f64], period: usize) -> Vec<f64> {
        let mut roc = Vec::with_capacity(data.len());
        if data.len() < period {
            return roc;
        }

        for i in period..data.len() {
            let value = (data[i] - data[i - period]) / data[i - period] * 100.0;
            roc.push(value);
        }

        roc
    }

    /// 计算买压
    fn calculate_buying_pressure(&self, close: &[f64], high: &[f64], low: &[f64]) -> f64 {
        let mut bp_sum = 0.0;
        let mut tr_sum = 0.0;

        for i in 1..close.len() {
            let bp = close[i] - low[i].min(close[i - 1]);
            let tr = high[i].max(close[i - 1]) - low[i].min(close[i - 1]);
            bp_sum += bp;
            tr_sum += tr;
        }

        if tr_sum != 0.0 {
            bp_sum / tr_sum
        } else {
            0.0
        }
    }

    /// 计算波动率
    fn calculate_volatility(&self, prices: &[f64]) -> f64 {
        if prices.len() < 2 {
            return 0.0;
        }

        let returns: Vec<f64> = prices.windows(2)
            .map(|w| (w[1] - w[0]) / w[0])
            .collect();

        let mean = returns.iter().sum::<f64>() / returns.len() as f64;
        let variance = returns.iter()
            .map(|&r| (r - mean).powi(2))
            .sum::<f64>() / returns.len() as f64;

        variance.sqrt()
    }

    /// 计算成交量趋势
    fn calculate_volume_trend(&self, volumes: &[f64]) -> f64 {
        if volumes.len() < 2 {
            return 0.0;
        }

        let avg_volume = volumes.iter().sum::<f64>() / volumes.len() as f64;
        let latest_volume = volumes[volumes.len() - 1];

        (latest_volume - avg_volume) / avg_volume
    }
}